package com.giaothong.model;

import java.util.ArrayList;
import java.util.List;

import org.json.JSONObject;

import com.giaothong.model.entity.DistanceEntity;
import com.giaothong.model.entity.StepEntity;
import com.giaothong.utils.ALog;
import com.giaothong.utils.JSONUtil;
import com.google.android.maps.GeoPoint;

public class ModelGetDirectionTwoLocationRequests {
	private DistanceEntity distance; // khoang cach giua 2 diem
	private DistanceEntity duration; // thoi gian di chuyen
	private String startAddress; // diem bat dau
	private String endAddress; // diem cuoi cung
	private GeoPoint startLocation;
	private GeoPoint endLocation;
	private ArrayList<StepEntity> step; // luu tru cac buoc di
	private ArrayList<GeoPoint> stepPoint;

	/**
	 * setter & getter
	 */

	public void setDistance(DistanceEntity distance) {
		this.distance = distance;
	}

	public void setDuration(DistanceEntity duration) {
		this.duration = duration;
	}

	public void setEndAddress(String endAddress) {
		this.endAddress = endAddress;
	}

	public void setEndLocation(GeoPoint endLocation) {
		this.endLocation = endLocation;
	}

	public void setStartAddress(String startAddress) {
		this.startAddress = startAddress;
	}

	public void setStartLocation(GeoPoint startLocation) {
		this.startLocation = startLocation;
	}

	public void setStep(ArrayList<StepEntity> step) {
		this.step = step;
	}

	public void setStepPoint(ArrayList<GeoPoint> stepPoint) {
		this.stepPoint = stepPoint;
	}

	public ArrayList<GeoPoint> getStepPoint() {
		return stepPoint;
	}

	public ArrayList<StepEntity> getStep() {
		return step;
	}
	public DistanceEntity getDistance() {
		return distance;
	}

	public DistanceEntity getDuration() {
		return duration;
	}

	public String getEndAddress() {
		return endAddress;
	}

	public GeoPoint getEndLocation() {
		return endLocation;
	}

	public String getStartAddress() {
		return startAddress;
	}

	public GeoPoint getStartLocation() {
		return startLocation;
	}

	/**
	 * contructor
	 */

	public ModelGetDirectionTwoLocationRequests() {
		setDefautValue();
	}

	public ModelGetDirectionTwoLocationRequests(JSONObject jsonObject) {
		setDefautValue();
		if (jsonObject == null)
			return;

		if (JSONUtil.jsonArrayTryGetValue(jsonObject, "routes") == null || JSONUtil.jsonArrayTryGetValue(jsonObject, "routes").size() == 0)
			return;

		ArrayList<JSONObject> legs = JSONUtil.jsonArrayTryGetValue(JSONUtil.jsonArrayTryGetValue(jsonObject, "routes").get(0), "legs");

		if (legs == null || legs.size() == 0)
			return;

		ArrayList<JSONObject> jsonStep = JSONUtil.jsonArrayTryGetValue(legs.get(0), "steps");

		ALog.d("step", jsonStep.get(0) + "");

		for (int i = 0; i < jsonStep.size(); i++) {
			this.step.add(new StepEntity(jsonStep.get(i)));
			this.stepPoint.addAll(decodePolyLine(JSONUtil.stringTryGetValue(JSONUtil.jsonObjectTryGetValue(jsonStep.get(i), "polyline"), "points")));
		}

		this.distance = new DistanceEntity(JSONUtil.jsonObjectTryGetValue(legs.get(0), "distance"));
		this.duration = new DistanceEntity(JSONUtil.jsonObjectTryGetValue(legs.get(0), "duration"));
		this.endAddress = JSONUtil.stringTryGetValue(legs.get(0), "end_address");
		this.startAddress = JSONUtil.stringTryGetValue(legs.get(0), "start_address");
		this.endLocation = JSONUtil.geoPointTryGetValue(legs.get(0), "end_location");
		this.startLocation = JSONUtil.geoPointTryGetValue(legs.get(0), "start_location");

	}

	/**
	 * set defaut value
	 */
	private void setDefautValue() {
		this.distance = new DistanceEntity();
		this.duration = new DistanceEntity();
		this.endAddress = "";
		this.endLocation = new GeoPoint(0, 0);
		this.startAddress = "";
		this.startLocation = new GeoPoint(0, 0);
		this.step = new ArrayList<StepEntity>();
		this.stepPoint = new ArrayList<GeoPoint>();
	}

	/**
	 * Decode a polyline string into a list of GeoPoints.
	 * 
	 * @param poly
	 *            polyline encoded string to decode.
	 * @return the list of GeoPoints represented by this polystring.
	 */

	private List<GeoPoint> decodePolyLine(final String poly) {
		int len = poly.length();
		int index = 0;
		List<GeoPoint> decoded = new ArrayList<GeoPoint>();
		int lat = 0;
		int lng = 0;

		while (index < len) {
			int b;
			int shift = 0;
			int result = 0;
			do {
				b = poly.charAt(index++) - 63;
				result |= (b & 0x1f) << shift;
				shift += 5;
			} while (b >= 0x20);
			int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
			lat += dlat;

			shift = 0;
			result = 0;
			do {
				b = poly.charAt(index++) - 63;
				result |= (b & 0x1f) << shift;
				shift += 5;
			} while (b >= 0x20);
			int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
			lng += dlng;

			decoded.add(new GeoPoint((int) (lat * 1E6 / 1E5), (int) (lng * 1E6 / 1E5)));
		}

		return decoded;
	}

}
